<?php

/**
 * form define as list of element,
 * element has attribute, validate, filter
 * validate called one has validate called.
 */
class AEngine_Form {

  /**
   *
   * @var midex
   */
  protected $_errors;
  /**
   * @var mixed
   */
  protected $_attrs;
  /**
   *
   * @var array of attribute
   */
  protected $_eles = array();

  /**
   * create a form
   * @param  array $attributes
   * @param  array $elements
   */
  public function __construct(&$attrs = NULL) {
    $this->_attrs = $attrs ? $attrs : array('method' => 'post');
  }

  public function setup($form_id = '') {
    $sql = "
            select fo.*, fe.class_name from yns_form_field as fo
            left join yns_field as fe on(fo.field_id = fe.id)
            where fo.form_id = 'signup'
            and fo.status = 1
            order by fo.priority;
            ";
    $rows = db::factory()->fetchAll($sql);

    foreach ($rows as $row) {
      $name = $row['name'];
      $class_name = $row['class_name'];
      $attrs = array();
      $params = (array) unserialize($row['params']);
      $this->_eles[$name] = new $class_name($name, $attrs, $params);
    }
  }

  /**
   *
   * @param  string $name
   * @return string
   */
  public function get_attr($name) {
    return @$this->_attrs[$name];
  }

  /**
   *
   * @param  string $name
   * @return string
   */
  public function set_attr($name, $value) {
    return $this->_attrs = $value;
  }

  public function get_elements() {
    return $this->_eles;
  }

  /**
   *
   * @param  string $name
   * @return form_ele
   */
  public function get_element($name) {
    return @$this->_eles[$name];
  }

  /**
   * @param  array $attrs
   * @return string
   */
  public static function join_attrs(&$attrs) {
    $ret = '';
    if ($attrs) {
      foreach ($attrs as $key => $value) {
        $ret .= sprintf('%s="%s"', $key, $value) . ' ';
      }
    }
    return $ret;
  }

  public function set_data($data) {
    if ($data && is_array($data)) {
      foreach ($data as $name => $value) {
        $ele = @$this->_eles[$name];
        if ($ele instanceof field_base) {
          $ele->set_value($value);
        }
      }
    }
  }

  public function &get_data() {
    $data = array();
    foreach ($this->_eles as $name => $ele) {
      $data[$name] = $ele->get_value();
    }
    return $data;
  }

  /**
   *
   * @param  array $data
   * @return bool
   */
  public function validate($data = NULL) {
    $result = true;
    $this->_errors = false;
    $this->set_data($data);
    foreach ($this->_eles as $name => $ele) {
      $ele->validate(@$data[$name]);
      if (!$ele->is_valid()) {
        $this->_errors[$name] = $ele->get_errors();
      }
    }
    return $result;
  }

  /**
   * get all error message or false if no errors
   * @return mixed
   */
  public function get_errors() {
    return $this->_errors;
  }

}